// Ipij API (c) Copyright 2012, designed by B.Mazin & G.Tartavel

/**
 * @fileOverview Provide some clustering functions.
 * @author TM = Tartavel & Mazin
 * @version 1.0
 */

/**
 *  @namespace
 *  Clustering functions.
 */
var Clustering = {};

/** Conversion between 2D / data arrays.<br />
 * A 2D array is an array of 'd' arrays: these are the components.<br />
 * A data array is a Float64Array with the components put togethers.
 * @param {Array} array
 *  An array of array, or a data array.
 * @return {Array}
 *  A data / 2D array.
 */
Clustering.convertArray = function (array) {
    'use strict';
    var errMsg = 'Clustering.convertArray: ';
    var ArrayType = Float64Array || Array;
    if (!array || !array.length) {
        throw new Error(errMsg + 'expected an array as argument');
    }
    // Convert
    var t, i, j, k, N, d;
    if (array[0].length) {
        d = array.length;
        N = array[0].length;
        t = new ArrayType(N * d);
        t.d = d;
        for (k = 0; k < d; k++) {
            if (array[k].length !== N) {
                throw new Error(errMsg + '2D array must be rectangular');
            }
            for (i = 0, j = k; i < N; i++, j += d) {
                // j = i*d + k
                t[j] = array[k][i];
            }
        }
    } else {
        if (!array.d || array.length % array.d) {
            throw new Error(errMsg + 'invalid data array');
        }
        d = array.d;
        N = Math.floor(array.length / d);
        t = [];
        for (k = 0; k < d; k++) {
            var tk = new ArrayType(N);
            for (i = 0, j = k; i < N; i++, j += d) {
                // j = i*d + k
                tk[i] = array[j];
            }
            t.push(tk);
        }
    }
    // Return
    return t;
};

Clustering.gmm = function (data, model) {
    'use strict';
};

Clustering.gmm_assign = function (data, model) {
    'use strict';
};

Clustering.gmm_model = function (data, softAssignment, modelType) {
    'use strict';
};

/** @private
 *  Soft to hard assignment.
 */
Clustering.softToHard = function (softAssignment) {
    'use strict';
    var errMsg = 'Clustering.softToHard: ';
    var k, d = softAssignment.d;
    if (!d) {
        throw new Error(errMsg + 'invalid assignment array');
    }
    var hardAssignment = [];
    var i, j, N = Math.floor(softAssignment.lengt / d);
    for (i = 0, j = 0; i < N; i++) {
        var best = 0;
        var bestProba = -1;
        for (k = 0; k < d; k++, j++) {
            // j = i*d + k
            if (softAssignment[j] > bestProba) {
                best = k;
                bestProba = softAssignment[j];
            }
            hardAssignment[i] = best;
        }
    }
    return hardAssignment;
};